/**
 * @ Author: luoqi
 * @ Create Time: 2025-07-12 16:22
 * @ Modified by: luoqi
 * @ Modified time: 2025-07-16 00:25
 * @ Description: This file is a ymodem protocol implementation
 */

#ifndef _LRBSB_H_
#define _LRBSB_H_ 

#ifdef __cplusplus
extern "C" {
#endif

#include <stdint.h>
#include <stddef.h>

typedef enum {
    YMODEM_SOH = 0x01, // 133 Byte frame
    YMODEM_STX = 0x02, // 1204 Byte frame
    YMODEM_EOT = 0x04, // file transfer end
    YMODEM_ACK = 0x06, // recv ok
    YMODEM_NAK = 0x15, // recv failed, retry
    YMODEM_CAN = 0x18, // send 5 times to cancel this transfer
    YMODEM_C   = 0x43  // char C 
} YModemCmd;

typedef enum {
    YMODEM_ERR_BUSY = -9,
    YMODEM_ERR_CRC = -8,
    YMODEM_ERR_SEND = -7,
    YMODEM_ERR_RECV = -6,
    YMODEM_ERR_READ = -5,
    YMODEM_ERR_WRITE = -4,
    YMODEM_ERR_FILENAME = -3,
    YMODEM_ERR_TIMEOUT = -2,
    YMODEM_ERR_PARAM = -1,
    YMODEM_ERR_NONE = 0,
} YModemErr;

typedef enum {
    YMODEM_STATE_HANDSHAKE = 0,
    YMODEM_STATE_START,
    YMODEM_STATE_TRANSFER,
    YMODEM_STATE_END,
    YMODEM_STATE_ERR,
} YModemState;

typedef enum {
    YMODEM_MODE_IDLE, // ymodem idle mode
    YMODEM_MODE_RB, // ymodem receive mode
    YMODEM_MODE_SB, // ymodem send mode
} YModemMode;
 
typedef int (*YModemSend)(const void *data, size_t sz, size_t timeout);
typedef int (*YModemRecv)(void *data, size_t sz, size_t timeout);
typedef int (*YModemWrite)(void *addr, size_t offset, const void *data, size_t sz);
typedef int (*YModemRead)(void *addr, size_t offset, void *data, size_t sz);

typedef struct {
    uint8_t packnum;
    size_t filesz;
    size_t recvsz;
    size_t packsz;
    size_t timeout;
    size_t retry;
    size_t retry_cnt;
    size_t handshake_cnt;
    YModemMode mode;
    YModemErr err;
    YModemState state;
    YModemState last_state;
    YModemSend send; // data send interface
    YModemRecv recv; // data recv interface
    YModemWrite write; // file or memery write interface
    YModemRead read; // file or memery read interface
} YModem;

int lrbsb_init(YModem *ymodem, YModemSend send, YModemRecv recv, YModemWrite write, YModemRead read, size_t timeout, size_t retry);

int lrb(YModem *ymodem, const char *filename, void *ptr);

int lsb(YModem *ymodem, const char *filename, const void *ptr, size_t sz);

#ifdef __cplusplus
}
#endif
#endif
